﻿#region USING
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text.RegularExpressions;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;
using System.Net;
using System.IO;
using System.Text;
using System.Net.Sockets;
using System.Reflection;
using System.Diagnostics;
#endregion

public partial class Client : Form
{
    #region ПЕРЕМЕННЫЕ
    public Proect proekt = null;
    public static Nastr nastr;
    UserState state, laststate;
    public object locker = new object();
    bool started;
    public Dictionary<string, Shover> shovers = new Dictionary<string, Shover>();
    public List<Rezult> rezults = new List<Rezult>();
    public Worker worker;
    const string for_google = "ФAffapogsahasgoaisyrhqwl,tlLJGfaoga15bsdgalkgjakhgas;glshg55ФАФПЭХПТЬФпыолдпиывывап124154лпыврпмывдпывоь512пмвтпа";
    #endregion
    #region Конструктор

    public Client()
    {
        InitializeComponent();

        panel_editor.Dock = DockStyle.Fill;
        panel_proect.Dock = DockStyle.Fill;
        panel_message.Dock = DockStyle.Fill;
        panel_nastr.Dock = DockStyle.Fill; 
        nastr = new Nastr();
       

        pg.SelectedObject = nastr;
        this.Show();
        GetProject();
    }

    void GetProject()
    {
        List<FileInfo> proekts = FILE.GetDirInfo(Proect.ext);
        if (proekts.Count > 0)
        {
            proekt = new Proect(this, proekts[0].Name);
            state = UserState.Loaded;
            ToLog(new Log(LogType.событие, "Найдено проектов: " + proekts.Count + " Загружаю последний: " + proekts[0].Name), true);
            UpdateZapros();
        }
        else
        {
            if (state != UserState.Editor)
            {
                New_Proect();
                ToLog(new Log(LogType.событие, "В папке с программой не найдено ни одного проекта. Отредактируйте новый проект!"), true);
            }
        }

        dgv.AutoGenerateColumns = false;
        dgv.Columns["col_slovo"].DataPropertyName = "slovo";
        dgv.Columns["col_yandex"].DataPropertyName = "yandex";
        dgv.Columns["col_google"].DataPropertyName = "google";

        browser.Navigate("http://www.google.ru/search?q=hello");
    }
   
    void HideAllExcept(Panel panel)
    {
        if(!panel.Visible)
            panel.Show();
        if (panel != panel_editor && panel_editor.Visible)
            panel_editor.Hide();
        if (panel != panel_proect && panel_proect.Visible)
            panel_proect.Hide();
        if (panel != panel_message && panel_message.Visible)
            panel_message.Hide();
        if (panel != panel_nastr && panel_nastr.Visible)
            panel_nastr.Hide();
    }
    #endregion
    #region РЕЗУЛЬТАТ

    void AddRez(Rezult rez)
    {
        rezults.Add(rez);
      
        if (shovers.ContainsKey(rez.key))
        {
            if (rez.poisk == 0)// yandex
                shovers[rez.key].yandex = rez.pos.ToString();
            else
                shovers[rez.key].google = rez.pos.ToString();
            dgv.Refresh();
        }
        else
        {
            Shover sh = new Shover() { dt=rez.dt, slovo=rez.slovo };
            if (rez.poisk == 0)// yandex
                sh.yandex = rez.pos.ToString();
            else
                sh.google = rez.pos.ToString();
            shovers.Add(rez.key, sh);
            dgv.DataSource = new BindingSource(shovers.Values, null);
        }
        dgv.FirstDisplayedScrollingRowIndex = dgv.Rows.Count - 1;
    }
   
    
    #endregion
    #region КАЛБАК АПДЕЙТЕР
    public void Call(MethodInvoker callback)
    {
        if (this.InvokeRequired)
            this.BeginInvoke(callback);
        else
            callback();
    }
    public void CheckTask(Task task, bool operation)
    {
        Call(delegate
        {
            if (operation)
                lb_tasks.Items.Add(task);
            else
                lb_tasks.Items.Remove(task);
        });
    }
    public void ToLog(Log log, bool show)
    {
        Call(delegate {
            if (!tb_log.IsDisposed)
                tb_log.AppendText(log.dt.Hour+":"+log.dt.Minute+":"+log.dt.Second + " " + log.message + "\r\n");
            if (show)
            {
                laststate = state;
                state = UserState.Message;
                tb_message.Text = log.message;
            }
        });
    }
    #endregion
    #region ТАЙМЕР
    int mes_time;
    private void timer1_Tick(object sender, EventArgs e)
    {
        if (worker != null && worker.tasks.Count > 0 && worker.task == null) worker.Work();
        if (started)
            b_start.Text = "Стоп";
        else
            b_start.Text = "Старт";


        if (!nastr.log && spc_top.Visible == true)
        {
            spc_top.Hide();
            lb_tasks.Parent = splitContainer4.Panel1;
        }
        if (nastr.log && spc_top.Visible == false)
        {
            lb_tasks.Parent = spc_top.Panel2;
            spc_top.Show();
        }

        
        if (state == UserState.Loaded)
        {
            this.Text = proekt.ToString() +" Y="+nastr.yandex+"ms, G="+nastr.google+"ms";
            HideAllExcept(panel_proect);
        }
        if (state == UserState.Message)
        {
          
            if (mes_time < nastr.mess_time)
                mes_time += timer1.Interval;
            else
            {
                mes_time = 0;
                state = laststate;
            }
           
            this.Text = "Сообщение системы";
            HideAllExcept(panel_message);
        }
        if (state == UserState.Editor)
        {
            this.Text = "Редактор проекта";
            HideAllExcept(panel_editor);
        }
        if (state == UserState.Настройки)
        {
            HideAllExcept(panel_nastr);
            this.Text = "Редактор настроек";
        }
    }
    void UpdateZapros()
    {
        chlb_poisk.Items.Clear();
        foreach (Poisk p in Poisk.List)
            chlb_poisk.Items.Add(p, true);
        chlb_slova.Items.Clear();
        foreach (Zapros z in proekt.zaproses)
            chlb_slova.Items.Add(z.slovo, z.used);
    }
    #endregion
    #region Проект эдитор
    public void New_Proect()
    {
        state = UserState.Editor;
        panel_editor.BringToFront();
    }
    private void button2_Click(object sender, EventArgs e)
    {
        if (!(this.tb_name.Text.Length > 0) || !(this.tb_slova.Text.Length > 0) || !(this.tb_Home.Text.Length > 0))
        {
            ToLog(new Log(LogType.событие,"Необходимо заполнить все поля!"), true);
            return;
        } 
        proekt = new Proect();
        proekt.name = this.tb_name.Text;
        proekt.home = this.tb_Home.Text;
        string cleare = this.tb_slova.Text.Replace(";", "");
        string[] found = cleare.Split(new string[] { "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries);
        foreach (string s in found)
            proekt.zaproses.Add(new Zapros(s, true));
        proekt.Save();
        state = UserState.Loaded;
        ToLog(new Log(LogType.событие,"Успешное сохранение проекта \"" + proekt.name + "\""), true);
        UpdateZapros();
        
    }
   
    #endregion
    #region Message
    private void button1_Click(object sender, EventArgs e)
    {
        panel_message.SendToBack();
        state = laststate;
    }
    #endregion
    #region START
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Client());

    } 
    #endregion
    #region ContexMenu
    private void asdasdToolStripMenuItem_Click(object sender, EventArgs e)
    {
        tb_name.Text = proekt.name;
        tb_Home.Text = proekt.home;
        tb_slova.Text = proekt.get_zapros();
        state = UserState.Editor;
    }

    private void очиститьВсеToolStripMenuItem_Click(object sender, EventArgs e)
    {
        foreach (Zapros z in this.proekt.zaproses)
            z.used = false;
        this.chlb_slova.Items.Clear();
        foreach (Zapros z in this.proekt.zaproses)
            this.chlb_slova.Items.Add(z.slovo, z.used);
    }

    private void сортироватьToolStripMenuItem_Click(object sender, EventArgs e)
    {
        if (this.chlb_slova.Sorted == true)
            this.chlb_slova.Sorted = false;
        else
            this.chlb_slova.Sorted = true;
    }

    private void выделитьВсёToolStripMenuItem_Click(object sender, EventArgs e)
    {
        foreach (Zapros z in this.proekt.zaproses)
            z.used = true;
        this.chlb_slova.Items.Clear();
        foreach (Zapros z in this.proekt.zaproses)
            this.chlb_slova.Items.Add(z.slovo, z.used);
    }
    
    #endregion
    void Save()
    {
        if (proekt!= null)
            proekt.Save();
    }
    private void chlb_slova_ItemCheck(object o, ItemCheckEventArgs e)
    {
        if (((CheckedListBox)o).SelectedItem == null) return;
        string name = (string)((CheckedListBox)o).SelectedItem;
        Zapros z = this.proekt.zaproses.Find(za =>za.slovo == name);
        if (e.NewValue == CheckState.Checked)
            z.used = true;
        else
            z.used = false;
    }

    private void сохранитьПроектToolStripMenuItem_Click(object sender, EventArgs e)
    {
        proekt.Save();
    }
    private void b_start_Click(object sender, EventArgs e)
    {
       int bcount = 0;
       if (!started)
        {
            started = true;

            worker = new Worker(this, browser, AddRez);

            foreach (Zapros z in proekt.zaproses)
            {
                if (!z.used) continue;
                Task task;

                if (chlb_poisk.GetItemCheckState(0) == CheckState.Checked) //yandex
                {
                    task = new Task(Poisk.List[0], proekt.home, z.slovo);
                    worker.tasks.Add(task);
                    worker.waiter.Set();
                    CheckTask(task, true);
                    bcount++;
                }

                if (chlb_poisk.GetItemCheckState(1) == CheckState.Checked) //goggle
                {
                    task = new Task(Poisk.List[1], proekt.home, z.slovo);
                    worker.tasks.Add(task);
                    worker.waiter.Set();
                    CheckTask(task, true);
                    bcount++;
                }
            }
            if (bcount == 0) bcount = 1;
            worker.k = bcount;
        }
        else
        {
           started = false;
           rezults.Clear();
           lb_tasks.Items.Clear();
           worker.Abort();
        }
    }

    private void настройкиToolStripMenuItem_Click(object sender, EventArgs e)
    {
        state = UserState.Настройки;
        
    }

    private void button3_Click(object sender, EventArgs e)
    {
        nastr.Save();
        state = UserState.Loaded;
        ToLog(new Log(LogType.событие, "Успешное сохранение настроек"), true);
    }

    private void копироватьВБуферToolStripMenuItem_Click(object sender, EventArgs e)
    {
        DataObject dataObj = dgv.GetClipboardContent();
        if (dataObj == null)
            ToLog(new Log(LogType.ошибка, "Нечего копировать"), true);
        else
            Clipboard.SetDataObject(dataObj, true);
    }

    private void очиститьToolStripMenuItem_Click(object sender, EventArgs e)
    {
        shovers.Clear();
        dgv.Rows.Clear();
        dgv.Refresh();
    }
}

